package Server

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
)

var db *sql.DB //连接池对象
func initDB() (err error) {
	//数据库
	//用户名:密码啊@tcp(ip:端口)/数据库的名字
	dsn := "root:123456@tcp(127.0.0.1:3306)/yami_shops?charset=utf8mb4&parseTime=True&loc=Local"
	//连接数据集
	db, err = sql.Open("mysql", dsn) //open不会检验用户名和密码
	if err != nil {
		return
	}
	err = db.Ping() //尝试连接数据库
	if err != nil {
		return
	}
	fmt.Println("连接数据库成功~")
	//设置数据库连接池的最大连接数
	db.SetMaxIdleConns(100)
	return
}

func handleConnections(w http.ResponseWriter, r *http.Request) {

	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Fatal(err)
	}
	// Make sure we close the connection when the function returns
	defer func(ws *websocket.Conn) {
		err := ws.Close()
		if err != nil {
			log.Printf("error: %v", err)
		}
	}(ws)

	//将token作为用户id，每次请求的时候带上token可以标识当前用户，然后别的websocket连接发送Shopid的时候就可以看到
	token := r.URL.Query().Get("token")
	log.Printf("token: %v", token)
	clients[token] = ws
	connToID[ws] = token
	for {
		// Read in a new message as JSON and map it to a Message object
		_, p, err := ws.ReadMessage()
		if err != nil {
			if closeErr, ok := err.(*websocket.CloseError); ok {
				switch closeErr.Code {
				case websocket.CloseNormalClosure:
					log.Println("WebSocket closed normally.")
				case websocket.CloseGoingAway:
					log.Println("WebSocket closed: going away.")
				default:
					log.Printf("WebSocket closed with error: %v\n", closeErr)
				}
			} else {
				log.Printf("WebSocket error: %v\n", err)
				userID := connToID[ws]
				delete(clients, userID)
				delete(connToID, ws)
				break
			}
		}
		messagestr := string(p)
		// 检查是否是心跳消息
		if string(p) == "~" {
			log.Printf("HeartBeat: %v", messagestr)
			continue // 忽略心跳消息，等待下一条消息
		}
		// Read in a new message as JSON and map it to a Message object
		fmt.Printf("Received message: %s\n", string(p))
		var wsData Message
		jsonerr := json.Unmarshal([]byte(string(p)), &wsData)
		if jsonerr != nil {
			log.Printf("JSON Unmarshal error: %v", err)
			userID := connToID[ws]
			delete(clients, userID)
			delete(connToID, ws)
			break
		}
		log.Printf("wsData: %v", wsData)
		broadcast <- wsData
	}
}

func handleMessages() {
	for {
		// Grab the next message from the broadcast channel
		msg := <-broadcast
		// Send it out to every client that is currently connected
		if msg.Data.From.String() == "1" {
			log.Printf("msg.Data.UserId.String(): %v", msg.Data.UserId)
			if client, ok := clients[msg.Data.UserId]; ok {
				//msg.Data.Message = "Hello From Server"
				err := client.WriteJSON(msg)
				if err != nil {
					log.Printf("error: %v", err)
					client.Close()
					delete(clients, msg.Data.UserId)
					delete(connToID, client)
				}
			}
		}
		if msg.Data.From.String() == "0" {
			if client, ok := clients[msg.Data.Shopid.String()]; ok {
				//msg.Data.Message = "Hello From Server"
				err := client.WriteJSON(msg)
				if err != nil {
					log.Printf("error: %v", err)
					client.Close()
					delete(clients, msg.Data.UserId)
					delete(connToID, client)
				}
			}
		}

	}
}
